home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 July: Mac OS SDK / Dev.CD Jul 99 SDK1.toast / Development Kits / Mac OS / OpenGL 1.0 SDK / Source / Libraries / glut / glut_menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-18  |  13.7 KB  |  660 lines  |  [TEXT/CWIE]

  1. /* Copyright (c) Mark J. Kilgard, 1994. */
  2.  
  3. /* This program is freely distributable without licensing fees
  4.    and is provided without guarantee or warrantee expressed or
  5.    implied. This program is -not- in the public domain. */
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <errno.h>
  11. #include <assert.h>
  12.  
  13. #include "glut.h"
  14. #include "glutint.h"
  15.  
  16. typedef struct glut_menu_rec {
  17.     char      label[50];
  18.     int       menuid;
  19.     struct glut_menu_bar_rec *sub_menu;
  20.     struct glut_menu_rec *next_menu;
  21. } glut_menu;
  22.  
  23. typedef struct glut_menu_bar_rec {
  24.     glut_menu   *menu;
  25.     void        (*select)(int value);
  26.     char        bar_label[50];
  27.     short       menuid;
  28.     MenuHandle  menu_handle;
  29.     short       menu_rsrc_id;
  30.     struct glut_menu_bar_rec *next_menu_bar;
  31. } glut_menu_bar;
  32.  
  33. static GLint          glut_unique_num  = 1;
  34. static glut_menu_bar  *cur_active_menu = NULL;
  35. static glut_menu_bar  *all_menus       = NULL;
  36.  
  37. static char glut_menu_names[MAX_MENUS][50] = {"LeftButton", "MiddleButton", "RightButton"};
  38.  
  39. static glut_menu_bar *__glutFindMenu(int menuid);
  40. static glut_menu *__glutFindMenuLastItem(glut_menu_bar *menu);
  41. static glut_menu *__glutFindMenuItem(glut_menu_bar *glut_menu_bar, int menuid);
  42. static glut_menu *__glutFindPrevMenuItem(glut_menu_bar *menu, int menuid);
  43. static glut_menu *__glutFindMenuIndex(glut_menu_bar *menu, int index);
  44. static glut_menu *__glutFindPrevMenuIndex(glut_menu_bar *menu, int index);
  45. static glut_menu *__glutCreateMenuEntry(const char *label, int value);
  46.  
  47. static glut_menu_bar *__glutFindMenu(int menuid)
  48. {
  49.     glut_menu_bar  *menu;
  50.     
  51.     menu = all_menus;
  52.     while(menu)
  53.     {
  54.         if(menu->menuid == menuid) break;
  55.         menu = menu->next_menu_bar;
  56.     }
  57.     
  58.     if(!menu) return NULL;
  59.     
  60.     return menu;
  61. }
  62.  
  63. static glut_menu *__glutFindMenuLastItem(glut_menu_bar *menu_bar)
  64. {
  65.     glut_menu  *last_menu;
  66.     
  67.     if(!menu_bar) return NULL;
  68.     
  69.     last_menu = menu_bar->menu;
  70.     while(last_menu && last_menu->next_menu)
  71.         last_menu = last_menu->next_menu;
  72.     
  73.     return last_menu;
  74. }
  75.  
  76. static glut_menu *__glutFindMenuItem(glut_menu_bar *menu_bar, int menuid)
  77. {
  78.     glut_menu  *menu_item;
  79.     
  80.     if(!menu_bar) return NULL;
  81.     
  82.     menu_item = menu_bar->menu;
  83.     while(menu_item)
  84.     {
  85.         if(menu_item->menuid == menuid) break;
  86.         menu_item = menu_item->next_menu;
  87.     }
  88.     
  89.     return menu_item;
  90. }
  91.  
  92. static glut_menu *__glutFindPrevMenuItem(glut_menu_bar *menu_bar, int menuid)
  93. {
  94.     glut_menu  *menu_item;
  95.     glut_menu  *prev_menu_item;
  96.     
  97.     if(!menu_bar) return NULL;
  98.     
  99.     prev_menu_item = NULL;
  100.     menu_item = menu_bar->menu;
  101.     while(menu_item)
  102.     {
  103.         if(menu_item->menuid == menuid) break;        
  104.         prev_menu_item = menu_item;
  105.         menu_item = menu_item->next_menu;
  106.     }
  107.     
  108.     return prev_menu_item;
  109. }
  110.  
  111. static glut_menu *__glutFindMenuIndex(glut_menu_bar *menu_bar, int index)
  112. {
  113.     glut_menu  *menu_item;
  114.     GLint i = 1;
  115.     
  116.     if(!menu_bar) return NULL;
  117.     
  118.     menu_item = menu_bar->menu;
  119.     while(menu_item)
  120.     {
  121.         if(index == i) break;
  122.         i++;
  123.         menu_item = menu_item->next_menu;
  124.     }
  125.     
  126.     return menu_item;
  127. }
  128.  
  129. static glut_menu *__glutFindPrevMenuIndex(glut_menu_bar *menu_bar, int index)
  130. {
  131.     glut_menu  *menu_item;
  132.     glut_menu  *prev_menu_item;
  133.     GLint i = 1;
  134.     
  135.     if(!menu_bar) return NULL;
  136.     
  137.     prev_menu_item = NULL;
  138.     menu_item = menu_bar->menu;
  139.     while(menu_item)
  140.     {
  141.         if(index == i) break;
  142.         i++;
  143.         prev_menu_item = menu_item;
  144.         menu_item = menu_item->next_menu;
  145.     }
  146.     
  147.     return prev_menu_item;
  148. }
  149.  
  150. static glut_menu *__glutCreateMenuEntry(const char *label, int value)
  151. {
  152.     glut_menu  *menu = (glut_menu *) malloc(sizeof(glut_menu));
  153.     if(!menu) return NULL;
  154.     
  155.     strcpy(menu->label, label);
  156.     menu->menuid    = value;
  157.     menu->sub_menu  = NULL;
  158.     menu->next_menu = NULL;
  159.     
  160.     return menu;
  161. }
  162.  
  163. void __glutBuildMenuBar(void)
  164. {
  165.     Handle menuBar;
  166.     
  167.     menuBar = GetNewMBar(rMenuBar);
  168.     if(!menuBar) return;
  169.     SetMenuBar(menuBar);
  170.     DisposeHandle(menuBar);
  171.     
  172.     AppendResMenu(GetMenuHandle(mApple),'DRVR');
  173.     DrawMenuBar();
  174. }
  175.  
  176. static void __glutRemoveMenuFromBar(int menunum)
  177. {
  178.     glut_menu_bar  *menu_bar;
  179.     
  180.     menu_bar = all_menus;
  181.     while(menu_bar)
  182.     {
  183.         if(menunum == menu_bar->menuid) break;
  184.         menu_bar = menu_bar->next_menu_bar;
  185.     }
  186.     
  187.     if(!menu_bar) return;
  188.     
  189.     if(menu_bar->menu_handle)
  190.     {
  191.         DeleteMenu(menu_bar->menu_rsrc_id);
  192.         DisposeMenu(menu_bar->menu_handle);
  193.         
  194.         menu_bar->menu_handle = NULL;
  195.         menu_bar->menu_rsrc_id = 0;
  196.     }
  197. }
  198.  
  199. static void __glutRemoveAllMenusFromBar(void)
  200. {
  201.     glut_menu_bar  *menu_bar;
  202.     
  203.     menu_bar = all_menus;
  204.     while(menu_bar)
  205.     {
  206.         if(menu_bar->menu_handle)
  207.         {
  208.             DeleteMenu(menu_bar->menu_rsrc_id);
  209.             DisposeMenu(menu_bar->menu_handle);
  210.             
  211.             menu_bar->menu_handle = NULL;
  212.             menu_bar->menu_rsrc_id = 0;
  213.         }
  214.         
  215.         menu_bar = menu_bar->next_menu_bar;
  216.     }
  217. }
  218.  
  219. static void __glutFreeMenuMem(int menunum)
  220. {
  221.     glut_menu_bar *menu_bar;
  222.     glut_menu_bar *prev_menu_bar;
  223.     glut_menu *menu;
  224.     glut_menu *next_menu;
  225.     
  226.     prev_menu_bar = NULL;
  227.     menu_bar = all_menus;
  228.     while(menu_bar)
  229.     {
  230.         if(menu_bar->menuid == menunum) break;
  231.         prev_menu_bar = menu_bar;
  232.         menu_bar = menu_bar->next_menu_bar;
  233.     }
  234.     
  235.     if(!menu_bar) return;
  236.     
  237.     if(prev_menu_bar)
  238.     {
  239.         prev_menu_bar->next_menu_bar = menu_bar->next_menu_bar;
  240.     }
  241.     else
  242.     {
  243.         all_menus = menu_bar->next_menu_bar;
  244.     }
  245.     
  246.     menu = menu_bar->menu;
  247.     while(menu)
  248.     {
  249.         next_menu = menu->next_menu;
  250.         free(menu);
  251.         menu = next_menu;
  252.     }
  253.     
  254.     if(menu_bar == cur_active_menu) cur_active_menu = NULL;
  255.     free(menu_bar);
  256. }
  257.  
  258. static glut_menu_bar *__glutGetMouseMenu(GLint mouse_id)
  259. {
  260.     glut_menu_bar *menu_bar;
  261.     int menu_id;
  262.     
  263.     if(!__glutCurrentWindow) return NULL;
  264.     
  265.     menu_id = __glutCurrentWindow->menus[mouse_id];
  266.     
  267.     if(menu_id == 0) return NULL;
  268.     
  269.     menu_bar = all_menus;
  270.     while(menu_bar)
  271.     {
  272.         if(menu_id == menu_bar->menuid) return menu_bar;
  273.         menu_bar = menu_bar->next_menu_bar;
  274.     }
  275.     
  276.     return NULL;
  277. }
  278.  
  279. void __glutRebuildMenuBar(void)
  280. {
  281.     glut_menu_bar  *menu_bar;
  282.     glut_menu      *menu_item, *sub_menu_item, *sub_sub_menu_item;
  283.     short          menu_id, mouse_id, item_id, sub_item_id;
  284.     Str255         pstr;
  285.     
  286.     if(!__glutCurrentWindow->fullscreen)
  287.     {
  288.         if(__glutCurrentWindow != __glutGetWindow((CGrafPtr) FrontWindow())) return;
  289.     }
  290.     
  291.     __glutRemoveAllMenusFromBar();
  292.     
  293.     if(!__glutCurrentWindow) return;
  294.     
  295.     menu_id = mMouseMenuStart;
  296.     for(mouse_id = 0; mouse_id < MAX_MENUS; mouse_id++)
  297.     {
  298.         menu_bar = __glutGetMouseMenu(mouse_id);
  299.         if(menu_bar)
  300.         {
  301.             __glutCToPStr(menu_bar->bar_label, pstr);
  302.             menu_bar->menu_handle = NewMenu(menu_id, pstr);
  303.             
  304.             if(menu_bar->menu_handle)
  305.             {
  306.                 InsertMenu(menu_bar->menu_handle, 0);
  307.                 menu_bar->menu_rsrc_id = menu_id++;
  308.                 
  309.                 item_id = 1;
  310.                 menu_item = menu_bar->menu;
  311.                 while(menu_item)
  312.                 {
  313.                     __glutCToPStr(menu_item->label, pstr);
  314.                     AppendMenu(menu_bar->menu_handle, pstr);
  315.                         
  316.                     if(menu_item->sub_menu)
  317.                     {
  318.                         __glutCToPStr(menu_item->label, pstr);
  319.                         menu_item->sub_menu->menu_handle = NewMenu(menu_id, pstr);
  320.                         
  321.                         if(menu_item->sub_menu->menu_handle)
  322.                         {
  323.                             menu_item->sub_menu->menu_rsrc_id = menu_id++;
  324.                             
  325.                             sub_item_id = 1;
  326.                             sub_menu_item = menu_item->sub_menu->menu;
  327.                             while(sub_menu_item)
  328.                             {
  329.                                 __glutCToPStr(sub_menu_item->label, pstr);
  330.                                 AppendMenu(menu_item->sub_menu->menu_handle, pstr);
  331.                                 
  332.                                 if(sub_menu_item->sub_menu)
  333.                                 {
  334.                                     __glutCToPStr(sub_menu_item->label, pstr);
  335.                                     sub_menu_item->sub_menu->menu_handle = NewMenu(menu_id, pstr);
  336.                                     
  337.                                     if(sub_menu_item->sub_menu->menu_handle)
  338.                                     {
  339.                                         sub_menu_item->sub_menu->menu_rsrc_id = menu_id++;
  340.                                         
  341.                                         sub_sub_menu_item = sub_menu_item->sub_menu->menu;
  342.                                         while(sub_sub_menu_item)
  343.                                         {
  344.                                             __glutCToPStr(sub_sub_menu_item->label, pstr);
  345.                                             AppendMenu(sub_menu_item->sub_menu->menu_handle, pstr);
  346.                                             
  347.                                             sub_sub_menu_item = sub_sub_menu_item->next_menu;
  348.                                         }
  349.                                         
  350.                                         SetItemCmd(menu_item->sub_menu->menu_handle, sub_item_id, hMenuCmd);
  351.                                         SetItemMark(menu_item->sub_menu->menu_handle, sub_item_id, sub_menu_item->sub_menu->menu_rsrc_id);
  352.                             
  353.                                         InsertMenu(sub_menu_item->sub_menu->menu_handle, hierMenu);
  354.                                     }
  355.                                 }
  356.                                 
  357.                                 sub_item_id++;
  358.                                 sub_menu_item = sub_menu_item->next_menu;
  359.                             }
  360.                             
  361.                             SetItemCmd(menu_bar->menu_handle, item_id, hMenuCmd);
  362.                             SetItemMark(menu_bar->menu_handle, item_id, menu_item->sub_menu->menu_rsrc_id);
  363.                             
  364.                             InsertMenu(menu_item->sub_menu->menu_handle, hierMenu);
  365.                         }
  366.                     }
  367.                     
  368.                     item_id++;
  369.                     menu_item = menu_item->next_menu;
  370.                 }
  371.             }
  372.         }
  373.     }
  374.     
  375.     DrawMenuBar();
  376. }
  377.  
  378. void __glutMenuKeyCommand(void)
  379. {
  380.     
  381. }
  382.  
  383. void __glutMenuCommand(short menuNum, short itemNum)
  384. {
  385.     glut_menu_bar  *menu_bar;
  386.     glut_menu      *menu_item;
  387.     short          menu_item_id;
  388.     glut_menu_bar  *old_active_menu;
  389.     
  390.     menu_bar = all_menus;
  391.     while(menu_bar)
  392.     {
  393.         if(menu_bar->menu_rsrc_id == menuNum)
  394.         {
  395.             menu_item = menu_bar->menu;
  396.             menu_item_id = 1;
  397.             while(menu_item)
  398.             {
  399.                 if(menu_item_id == itemNum)
  400.                 {
  401.                     old_active_menu = cur_active_menu;
  402.                     cur_active_menu = menu_bar;
  403.                     
  404.                     if(menu_bar->select) menu_bar->select(menu_item->menuid);
  405.                     
  406.                     cur_active_menu = old_active_menu;
  407.                     
  408.                     return;
  409.                 }
  410.                 
  411.                 menu_item = menu_item->next_menu;
  412.                 menu_item_id++;
  413.             }
  414.         }
  415.         
  416.         menu_bar = menu_bar->next_menu_bar;
  417.     }
  418. }
  419.  
  420. int __glutGetCurNumMenuItems(void)
  421. {
  422.     glut_menu *menu_item;
  423.     int count = 0;
  424.  
  425.     if(!cur_active_menu) return 0;
  426.     
  427.     menu_item = cur_active_menu->menu;
  428.     while(menu_item)
  429.     {
  430.         count++;
  431.         menu_item = menu_item->next_menu;
  432.     }
  433.     
  434.     return count;
  435. }
  436.  
  437. void glutMenuStateFunc(GLUTmenuStateCB menuStateFunc)
  438. {
  439.     __glutCurrentWindow->menu_state = menuStateFunc;
  440. }
  441.  
  442. void glutMenuStatusFunc(GLUTmenuStatusCB menuStatusFunc)
  443. {
  444.     __glutCurrentWindow->menu_status = menuStatusFunc;
  445. }
  446.  
  447. int glutCreateMenu(void (*select)(int value))
  448. {
  449.     glut_menu_bar  *menu_bar;
  450.     
  451.     /* Update menu bar list */
  452.     menu_bar = (glut_menu_bar *) malloc(sizeof(glut_menu_bar));
  453.     if(!menu_bar) return 0;
  454.     
  455.     menu_bar->menu          = NULL;
  456.     menu_bar->menuid        = glut_unique_num++;
  457.     menu_bar->menu_handle   = NULL;
  458.     menu_bar->menu_rsrc_id  = 0;
  459.     menu_bar->bar_label[0]  = 0;
  460.     menu_bar->select        = select;
  461.     
  462.     menu_bar->next_menu_bar = all_menus;
  463.      all_menus = menu_bar;
  464.     
  465.     /* Set current menu */
  466.     cur_active_menu = menu_bar;
  467.     
  468.     return menu_bar->menuid;
  469. }
  470.  
  471. void glutDestroyMenu(int menunum)
  472. {
  473.     __glutRemoveMenuFromBar(menunum);
  474.     __glutFreeMenuMem(menunum);
  475.     
  476.     DrawMenuBar();
  477. }
  478.  
  479. int glutGetMenu(void)
  480. {
  481.     if(cur_active_menu)
  482.         return cur_active_menu->menuid;
  483.     else
  484.         return 0;
  485. }
  486.  
  487. void glutSetMenu(int menuid)
  488. {
  489.     cur_active_menu = __glutFindMenu(menuid);
  490. }
  491.  
  492. void glutAddMenuEntry(const char *label, int value)
  493. {
  494.     glut_menu  *last_menu;
  495.     glut_menu  *new_menu;
  496.     
  497.     if(!cur_active_menu) return;
  498.     
  499.     /* Add it to the bottom of current menu */
  500.     last_menu = __glutFindMenuLastItem(cur_active_menu);
  501.     
  502.     /* Create menu entry */
  503.     new_menu = __glutCreateMenuEntry(label, value);
  504.     if(!new_menu) return;
  505.     
  506.     /* Add menu entry to last menu item */
  507.     if(last_menu) last_menu->next_menu = new_menu;
  508.     else cur_active_menu->menu = new_menu;
  509.     
  510.     /* Rebuild menu bar */
  511.     __glutRebuildMenuBar();
  512. }
  513.  
  514. void glutAddSubMenu(const char *label, int menu)
  515. {
  516.     glut_menu_bar  *sub_menu;
  517.     glut_menu  *new_menu;
  518.     glut_menu  *last_menu;
  519.     
  520.     if(!cur_active_menu) return;
  521.     
  522.     /* Find sub menu */
  523.     sub_menu = __glutFindMenu(menu);
  524.     if(!sub_menu) return;
  525.     
  526.     /* Add it to the bottom of current menu */
  527.     last_menu = __glutFindMenuLastItem(cur_active_menu);
  528.     
  529.     /* Create sub menu entry */
  530.     new_menu = __glutCreateMenuEntry(label, 0);
  531.     if(!new_menu) return;
  532.     
  533.     /* Add menu entry to current menu */
  534.     if(last_menu) last_menu->next_menu = new_menu;
  535.     else cur_active_menu->menu = new_menu;
  536.     
  537.     /* Attach sub menu to menu entry */
  538.     new_menu->sub_menu   = sub_menu;
  539.     
  540.     /* Rebuild menu bar */
  541.     __glutRebuildMenuBar();
  542. }
  543.  
  544. void glutChangeToMenuEntry(int num, const char *label, int value)
  545. {
  546.     glut_menu  *menu;
  547.     
  548.     if(!cur_active_menu) return;
  549.     
  550.     /* Find menu at index num */
  551.     menu = __glutFindMenuIndex(cur_active_menu, num);
  552.     if(!menu) return;
  553.     
  554.     /* Set menu index to menu value */
  555.     strcpy(menu->label, label);
  556.     menu->menuid   = value;
  557.     
  558.     /* Rebuild menu bar */
  559.     __glutRebuildMenuBar();
  560. }
  561.  
  562. void glutChangeToSubMenu(int num, const char *label, int menu)
  563. {
  564.     glut_menu  *index_menu;
  565.     glut_menu_bar  *sub_menu;
  566.     
  567.     if(!cur_active_menu) return;
  568.     
  569.     /* Find menu at index num */
  570.     index_menu = __glutFindMenuIndex(cur_active_menu, num);
  571.     if(!index_menu) return;
  572.     
  573.     /* Find sub menu */
  574.     sub_menu = __glutFindMenu(menu);
  575.     if(!sub_menu) return;
  576.     
  577.     /* Set menu index to sub menu values */
  578.     strcpy(index_menu->label, label);
  579.     index_menu->menuid = 0;
  580.     index_menu->sub_menu = sub_menu;
  581.     
  582.     /* Rebuild menu bar */
  583.     __glutRebuildMenuBar();
  584. }
  585.  
  586. void glutRemoveMenuItem(int num)
  587. {
  588.     glut_menu *menu;
  589.     glut_menu *prev_menu;
  590.     
  591.     if(!cur_active_menu) return;
  592.     
  593.     menu = __glutFindMenuIndex(cur_active_menu, num);
  594.     if(!menu) return;
  595.     
  596.     prev_menu = __glutFindPrevMenuIndex(cur_active_menu, num);
  597.     
  598.     if(prev_menu)
  599.         prev_menu->next_menu = menu->next_menu;
  600.     else
  601.         cur_active_menu->menu = menu->next_menu;
  602.         
  603.     free(menu);
  604.     
  605.     /* Rebuild menu bar */
  606.     __glutRebuildMenuBar();
  607. }
  608.  
  609. void glutAttachMenu(int button)
  610. {
  611.     if(!__glutCurrentWindow)
  612.     {
  613.         __glutWarning("glutAttachMenu: no active window");
  614.         return;
  615.     }
  616.     
  617.     if(!cur_active_menu) return;
  618.     
  619.     /* Set menu label to button name */
  620.     __glutCurrentWindow->menus[button] = cur_active_menu->menuid;
  621.     
  622.     strcpy(cur_active_menu->bar_label, glut_menu_names[button]);
  623.     
  624.     /* Rebuild menu bar */
  625.     __glutRebuildMenuBar();
  626. }
  627.  
  628. void glutAttachMenuName(int button, char *menu_name)
  629. {
  630.     if(!__glutCurrentWindow)
  631.     {
  632.         __glutWarning("glutAttachMenu: no active window");
  633.         return;
  634.     }
  635.     
  636.     if(!cur_active_menu) return;
  637.     
  638.     /* Set menu label to button name */
  639.     __glutCurrentWindow->menus[button] = cur_active_menu->menuid;
  640.     
  641.     strcpy(cur_active_menu->bar_label, menu_name);
  642.     
  643.     /* Rebuild menu bar */
  644.     __glutRebuildMenuBar();
  645. }
  646.  
  647. void glutDetachMenu(int button)
  648. {
  649.     if(!__glutCurrentWindow)
  650.     {
  651.         __glutWarning("glutDetachMenu: no active window");
  652.         return;
  653.     }
  654.     
  655.     __glutCurrentWindow->menus[button] = 0;
  656.     
  657.     /* Rebuild menu bar */
  658.     __glutRebuildMenuBar();
  659. }
  660.